package com.xiaoyang.billiards.architecture.life;

import com.xiaoyang.billiards.architecture.annotation.TestSpringLife;
import com.xiaoyang.billiards.architecture.common.Errors.ServiceError;
import com.xiaoyang.billiards.architecture.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 杨泽纬
 * @description TODO
 * @serviceName SpringLife
 * @date 2023/11/16
 */
@Slf4j
@Component
public class SpringLife implements BeanPostProcessor, SmartInitializingSingleton, DisposableBean {

    private final Map<String, MyAnnotationHandler> map = new HashMap<>();

    //private final Set<Class<?>> nonAnnotatedClasses = Collections.newSetFromMap(new ConcurrentHashMap(64));

    /**
     * bean的属性已经设置完毕，但还未进行初始化时被调用
     * @param bean bean
     * @param beanName beanName
     * @return bean
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        log.info("bean的属性已经设置完毕，但还未进行初始化时被调用 -> beanName:{}", beanName);
        return bean;
    }

    /**
     * bean的属性值已经被填充完毕。返回的bean实例可能是原始bean的一个包装
     * @param bean bean
     * @param beanName beanName
     * @return bean
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (bean instanceof AopInfrastructureBean) {
            return bean;
        } else {
            Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
            Method[] methods = targetClass.getMethods();
            for (Method method : methods) {
                TestSpringLife annotation = method.getAnnotation(TestSpringLife.class);
                if (annotation == null){
                    // 不存在注解，直接返回
                    return bean;
                }else {
                    // 存在注解，进行处理
                    String value = annotation.value();
                    if (StringUtils.isBlank(value)){
                        // value 为空
                        throw new ServiceException(ServiceError.ANNOTATION_ERROR, "注解value不能为空");
                    }
                    // 正常处理
                    map.put(value,new MyAnnotationHandler());

                }
            }
            map.forEach((k,v)->{
                log.info("key:{} value:{}",k,v);
            });
            log.info("注解 : {}",map.size());
            return bean;
        }
    }

    /**
     * SmartInitializingSingleton接口方法
     * 所有单例对象实例化之后被调用
     */
    @Override
    public void afterSingletonsInstantiated() {
        log.info("所有单例对象实例化之后被调用 : afterSingletonsInstantiated");
    }


    @Override
    public void destroy() {
        log.info("结束Spring整个流程时调用 : destroy");
    }
}
